import { h, shallowReactive, ref, reactive } from 'vue';
import {
  IPSEditor,
  IPSPanel,
  IPSPanelButton,
  IPSPanelContainer,
  IPSPanelField,
  IPSPanelItem,
  IPSPanelRawItem,
  IPSPanelTabPage,
  IPSPanelTabPanel,
} from '@ibiz/dynamic-model-api';
import { IEditorEventParam, IMobPanelController, IParam, MobPanelController, Util } from 'ibz-core';
import { AppMobPanelProps } from 'ibz-core';
import { GenerateComponent } from '../component-base';
import { CtrlComponentBase } from './ctrl-component-base';
import { AppLayoutContainer } from '../common/app-layout-container';
import { AppLayoutItem } from '../common/app-layout-item';

export class AppMobPanel extends CtrlComponentBase<AppMobPanelProps> {
  /**
   * @description 部件控制器
   * @protected
   * @type {IMobPanelController}
   * @memberof AppMobPanel
   */
  protected c!: IMobPanelController;

  /**
   * @description 当前选中分页
   * @type {*}
   * @memberof AppMobPanel
   */
  public currentTab: any = ref({});

  /**
   * @description 设置响应式
   * @memberof AppMobPanel
   */
  setup() {
    this.c = shallowReactive<MobPanelController>(this.getCtrlControllerByType('PANEL') as MobPanelController);
    super.setup();
  }

  /**
   * @description 初始化响应式属性
   * @memberof AppMobPanel
   */
  initReactive() {
    super.initReactive();
    this.c.detailsModel = reactive(this.c.detailsModel);
    this.c.dataMap = reactive(this.c.dataMap);
  }

  /**
   * @description 获取部件样式名
   * @return {*}
   * @memberof AppMobPanel
   */
  public getCtrlClassNames() {
    const cssName = (this.c.controlInstance as IPSPanel).getPSSysCss?.()?.cssName;
    const classNames = {
      [`app-${this.c.panelMode}-panel`]: true,
    };
    if (cssName) {
      Object.assign(classNames, {
        [cssName]: true,
      });
    }
    return classNames;
  }

  /**
   * 计算容器尺寸
   *
   * @param {number} value
   * @return {*}  {string}
   */
  public calcBoxSize(value: number, enableRem: boolean = false): string {
    if (value > 1) {
      return enableRem ? value / 50 + 'rem' : value + 'px';
    } else if (value > 0) {
      return value * 100 + '%';
    }
    return '100%';
  }

  /**
   * @description 获取顶级容器样式
   * @return {*}
   * @memberof AppMobPanel
   */
  public getRootStyle() {
    const height = (this.c.controlInstance as IPSPanel).height;
    const width = (this.c.controlInstance as IPSPanel).panelWidth;
    const style = {};
    if (width > 0) {
      Object.assign(style, { width: this.calcBoxSize(width, true), height: this.calcBoxSize(height, true) });
    } else {
      Object.assign(style, { width: '100%', height: '100%' });
    }
    return style;
  }

  /**
   * @description 获取面板项样式名
   * @param {IPSPanelItem} item 面板项
   * @return {*}
   * @memberof AppMobPanel
   */
  public getDetailClass(item: IPSPanelItem) {
    const { itemType, name } = item;
    const detailClass = {
      [`app-${this.c.panelMode}panel-${itemType.toLowerCase()}`]: true,
      [`panel-${itemType.toLowerCase()}-${name.toLowerCase()}`]: true,
    };
    const css = item.getPSSysCss?.();
    if (css) {
      Object.assign(detailClass, {
        [`${css.cssName}`]: true,
      });
    }
    return detailClass;
  }

  /**
   * @description 面板分页栏切换
   * @param {string} key 分页栏标识
   * @param {*} event 源事件对象
   * @memberof AppMobPanel
   */
  public segmentChanged(key: string, event: any) {
    if (key) {
      this.currentTab.value[key] = event.detail.value;
    }
  }

  /**
   * @description 面板按钮点击
   * @param {IParam} detail 数据
   * @param {*} event 源事件对象
   * @memberof AppMobPanel
   */
  public buttonClick(detail: IParam, event: any) {
    if (this.c.handleActionClick && this.c.handleActionClick instanceof Function) {
      this.c.handleActionClick(this.c.data, event, detail);
    }
  }

  /**
   * @description 渲染面板按钮
   * @param {IPSPanelButton} modelJson 按钮模型数据
   * @param {number} index 序列标识
   * @return {*}
   * @memberof AppMobPanel
   */
  public renderButton(modelJson: IPSPanelButton, index: number): any {
    const { caption, name, showCaption } = modelJson;
    const detailModel = this.c.detailsModel?.[name];
    //  模型显示
    if (detailModel && !detailModel.visible) {
      return;
    }

    const icon = modelJson.getPSSysImage();
    const uiAction = modelJson.getPSUIAction();
    const iconName = icon?.cssClass
      ? icon.cssClass
      : uiAction?.getPSSysImage()?.cssClass
      ? uiAction.getPSSysImage()?.cssClass
      : null;

    return (
      <AppLayoutItem
        class={this.getDetailClass(modelJson)}
        layoutMode={(modelJson.getParentPSModelObject() as any).getPSLayout()?.layout}
        layoutPos={modelJson.getPSLayoutPos() || undefined}
      >
        <ion-button
          disabled={detailModel && detailModel[name]?.disabled}
          onClick={(event: any) => {
            this.buttonClick(modelJson, event);
          }}
        >
          {iconName ? <app-icon name={iconName} /> : null}
          {showCaption ? this.$tl(modelJson.getCapPSLanguageRes()?.lanResTag, caption) : ''}
        </ion-button>
      </AppLayoutItem>
    );
  }

  /**
   * @description 渲染编辑器
   * @param {IPSEditor} editor 编辑器实例对象
   * @param {IPSPanelItem} parentItem 面板项对象
   * @return {*}
   * @memberof AppMobPanel
   */
  public renderEditor(editor: IPSEditor, parentItem: IPSPanelItem): any {
    const targetCtrlComponent: any = App.getComponentService().getEditorComponent(
      editor?.editorType,
      editor?.editorStyle ? editor?.editorStyle : 'DEFAULT',
      editor.getPSSysPFPlugin() ? `${editor?.editorType}_${editor?.editorStyle}` : undefined,
    );
    return h(targetCtrlComponent, {
      editorInstance: editor,
      containerCtrl: this.c.controlInstance,
      parentItem: parentItem,
      contextData: this.c.data,
      navContext: Util.deepCopy(this.c.context),
      navParam: Util.deepCopy(this.c.viewParam),
      disabled: this.c.detailsModel[editor.name]?.disabled,
      value: this.c.data[editor?.name || ''],
      onEditorEvent: (event: IEditorEventParam) => {
        this.c.handleEditorEvent(event);
      },
    });
  }

  /**
   * @description 渲染面板属性
   * @param {IPSPanelField} modelJson 面板属性对象
   * @param {number} index 序列标识
   * @return {*}
   * @memberof AppMobPanel
   */
  public renderField(modelJson: IPSPanelField, index: number): any {
    //  模型显示
    const detailModel = this.c.detailsModel?.[modelJson.name];
    if (detailModel && !detailModel.visible) {
      return;
    }
    const { caption } = modelJson;
    const editor = modelJson.getPSEditor();
    let customCode: boolean = false;
    if (this.c.dataMap && this.c.dataMap.get(modelJson.name)) {
      customCode = this.c.dataMap.get(modelJson.name)?.customCode;
    }
    return (
      <AppLayoutItem
        class={this.getDetailClass(modelJson)}
        layoutMode={(modelJson.getParentPSModelObject() as any).getPSLayout()?.layout}
        layoutPos={modelJson.getPSLayoutPos() || undefined}
      >
        {caption && (
          <ion-label class='panel-item-field-label'>
            {this.$tl(modelJson.getCapPSLanguageRes()?.lanResTag, caption)}
          </ion-label>
        )}
        {editor && !customCode ? this.renderEditor(editor, modelJson) : null}
        {customCode && h('div', { innerHTML: this.c.data[modelJson.name] })}
      </AppLayoutItem>
    );
  }

  /**
   * @description 渲染直接内容
   * @param {IPSPanelButton} modelJson 直接内容模型数据
   * @param {number} index 序列标识
   * @return {*}
   * @memberof AppMobPanel
   */
  public renderRawItem(modelJson: IPSPanelRawItem, index: number): any {
    //  模型显示
    const detailModel = this.c.detailsModel?.[modelJson.name];
    if (detailModel && !detailModel.visible) {
      return;
    }

    const { contentType, htmlContent, getPSSysImage, rawContent } = modelJson;
    if (rawContent) {
      //  TODO  国际化内容支持
      // const items = rawContent.match(/\{{(.+?)\}}/g);
      // if (items) {
      //     items.forEach((item: string) => {
      //       rawContent = rawContent.replace(/\{{(.+?)\}}/, item.substring(2, item.length - 2));
      //     });
      // }
    }
    let element: any = undefined;
    if (contentType == 'HTML' && htmlContent) {
      element = h('div', {
        innerHTML: htmlContent,
      });
    }
    let content: any;
    switch (contentType) {
      case 'HTML':
        content = element ? element : htmlContent;
        break;
      case 'RAW':
        content = rawContent;
        break;
      case 'IMAGE':
        content = <img src={getPSSysImage?.()?.imagePath} />;
        break;
      case 'MARKDOWN':
        content = <div>{this.$tl('widget.mobpanel.nomarkdown', 'MARKDOWN直接内容暂未支持')}</div>;
        break;
    }

    return (
      <AppLayoutItem
        class={this.getDetailClass(modelJson)}
        layoutMode={(modelJson.getParentPSModelObject() as any).getPSLayout()?.layout}
        layoutPos={modelJson.getPSLayoutPos() || undefined}
      >
        {content}
      </AppLayoutItem>
    );
  }

  /**
   * @description 渲染分页部件
   * @param {IPSPanelButton} modelJson 分页部件模型数据
   * @param {number} index 序列标识
   * @return {*}
   * @memberof AppMobPanel
   */
  public renderTabPage(modelJson: IPSPanelTabPage, index: number): any {
    //  模型显示
    const detailModel = this.c.detailsModel?.[modelJson.name];
    if (detailModel && !detailModel.visible) {
      return;
    }

    const parent = modelJson.getParentPSModelObject?.() as IPSPanelTabPanel;
    const currentKey = this.currentTab.value[parent?.name];
    if (currentKey == modelJson.name) {
      return (
        <div
          class={this.getDetailClass(modelJson)}
          style={[detailModel && !detailModel.visible ? 'display: none;' : '']}
        >
          <AppLayoutContainer layout={modelJson.getPSLayout() || undefined}>
            {modelJson.getPSPanelItems()?.map((item: IPSPanelItem, index: number) => {
              return this.renderByDetailType(item, index);
            })}
          </AppLayoutContainer>
        </div>
      );
    }
  }

  /**
   * @description 渲染分页面板
   * @param {IPSPanelButton} modelJson 分页面板模型数据
   * @param {number} index 序列标识
   * @return {*}
   * @memberof AppMobPanel
   */
  public renderTabPanel(modelJson: IPSPanelTabPanel, index: number): any {
    //  模型显示
    const detailModel = this.c.detailsModel?.[modelJson.name];
    if (detailModel && !detailModel.visible) {
      return;
    }

    const tabPages = modelJson.getPSPanelTabPages() || [];
    if (tabPages.length) {
      //  默认选中第一个分页
      if (!this.currentTab.value[modelJson.name]) {
        this.currentTab.value[modelJson.name] = tabPages[0].name;
      }

      // 绘制作为子项的布局绘制
      return (
        <AppLayoutItem
          class={this.getDetailClass(modelJson)}
          layoutMode={(modelJson.getParentPSModelObject() as any).getPSLayout()?.layout}
          layoutPos={modelJson.getPSLayoutPos() || undefined}
        >
          <div class='app-tabpanel__header'>
            <ion-segment
              value={this.currentTab.value[modelJson.name]}
              onIonChange={($event: any) => this.segmentChanged(modelJson.name, $event)}
            >
              {tabPages.map((page: IPSPanelTabPage, index: number) => {
                return (
                  <ion-segment-button value={page.name}>
                    <ion-label>{this.$tl(page.getCapPSLanguageRes()?.lanResTag, page.caption)}</ion-label>
                  </ion-segment-button>
                );
              })}
            </ion-segment>
          </div>
          <div class='app-tabpanel__content'>
            {tabPages.map((page: IPSPanelTabPage, index: number) => {
              return this.renderByDetailType(page, index);
            })}
          </div>
        </AppLayoutItem>
      );
    }
  }

  /**
   * @description 渲染面板容器
   * @param {IPSPanelButton} modelJson 面板容器模型数据
   * @param {number} index 序列标识
   * @return {*}
   * @memberof AppMobPanel
   */
  public renderContainer(modelJson: IPSPanelContainer, index: number): any {
    const { showCaption, caption, name } = modelJson;
    const detailModel = this.c.detailsModel?.[name];
    //  模型显示
    if (detailModel && !detailModel.visible) {
      return null;
    }
    return (
      <AppLayoutItem
        class={this.getDetailClass(modelJson)}
        layoutMode={(modelJson.getParentPSModelObject() as any).getPSLayout()?.layout}
        layoutPos={modelJson.getPSLayoutPos() || undefined}
      >
        {showCaption ? <ion-label>{this.$tl(modelJson.getCapPSLanguageRes()?.lanResTag, caption)}</ion-label> : null}
        <AppLayoutContainer layout={modelJson.getPSLayout() || undefined}>
          {modelJson.getPSPanelItems()?.map((item: IPSPanelItem, index: number) => {
            return this.renderByDetailType(item, index);
          })}
        </AppLayoutContainer>
      </AppLayoutItem>
    );
  }

  /**
   * @description 根据类型渲染面板项
   * @param {*} modelJson 面板项对象
   * @param {number} index 序列标识
   * @return {*}
   * @memberof AppMobPanel
   */
  public renderByDetailType(modelJson: any, index: number): any {
    if (modelJson.getPSSysPFPlugin()?.pluginCode) {
      const ctrlItemPluginInstance = App.getPluginService().getCtrlItemPluginByTag(
        modelJson.getPSSysPFPlugin()?.pluginCode,
      );
      if (ctrlItemPluginInstance) {
        return ctrlItemPluginInstance.renderItem(this.c.data[modelJson.name], this.c, this);
      }
    } else {
      switch (modelJson.itemType) {
        case 'CONTAINER':
          return this.renderContainer(modelJson, index);
        case 'BUTTON':
          return this.renderButton(modelJson, index);
        case 'FIELD':
          return this.renderField(modelJson, index);
        case 'RAWITEM':
          return this.renderRawItem(modelJson, index);
        case 'TABPANEL':
          return this.renderTabPanel(modelJson, index);
        case 'TABPAGE':
          return this.renderTabPage(modelJson, index);
      }
    }
  }

  /**
   * @description 渲染面板部件根节点
   * @return {*}
   * @memberof AppMobPanel
   */
  public renderRootPSPanelItems(): any {
    const panelItems = (this.c.controlInstance as IPSPanel).getRootPSPanelItems?.() || [];
    if (!panelItems.length) {
      return null;
    }
    return (
      <AppLayoutContainer
        class={this.getCtrlClassNames()}
        layout={(this.c.controlInstance as IPSPanel).getPSLayout() || undefined}
      >
        {panelItems.map((item: IPSPanelItem, index: number) => {
          return this.renderByDetailType(item, index);
        })}
      </AppLayoutContainer>
    );
  }

  /**
   * @description 渲染面板部件
   * @return {*}
   * @memberof AppMobPanel
   */
  render(): any {
    if (!this.controlIsLoaded.value || !this.c.controlInstance) {
      return null;
    }
    return (
      <div class={{ ...this.classNames }} style={this.getRootStyle()}>
        {this.renderPullDownRefresh()}
        {this.renderRootPSPanelItems()}
      </div>
    );
  }
}

export const AppMobPanelComponent = GenerateComponent(AppMobPanel, Object.keys(new AppMobPanelProps()));
